package com.example.zg.androidnewview.animator;

import android.animation.Animator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.SimpleItemAnimator;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;

import java.util.ArrayList;
import java.util.List;


/**
 * 创建日期:2019/1/15 on 17:05
 * 描述：
 * 作者: zhougan
 */
public  class BaseItemAnimator extends SimpleItemAnimator {
    private static final String TAG = "BaseItemAnimator";

    //存放将要执行的动画
    private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>();
    private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<>();
    private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
    private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
    //存放正在执行的一批动画
    private ArrayList<ArrayList<ViewHolder>> mAdditionsList = new ArrayList<>();
    private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
    private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
    //正在执行的动画
    private ArrayList<ViewHolder> mAddAnimations = new ArrayList<>();
    private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<>();
    private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>();
    private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<>();



    //当Item删除时被调用
    @Override
    public boolean animateRemove(ViewHolder holder) {
        Log.i(TAG, "animateRemove: ");
        mPendingRemovals.add(holder);
        return false;
    }

    //当Item添加时被调用
    @Override
    public boolean animateAdd(ViewHolder holder) {
        Log.i(TAG, "animateAdd: ");
        //开始动画前把item移动到左边看不见
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
        float tanX=-(holder.itemView.getWidth()+params.leftMargin);
        holder.itemView.setTranslationX(tanX);
        mPendingAdditions.add(holder);
        return true;
    }

    //当Item移动时被调用
    //这个方法的作用是在执行某个Item的动画时其它item的行为
    //比如我们要添加一个Item的位置为1，那么后面的Item要往下移，让出一个空位
    @Override
    public boolean animateMove(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
        Log.i(TAG, "animateMove: ");
        return true;
    }

    //当显式调用notifyItemChanged()或notifyDataSetChanged()时被调用
    //Item更新回调
    @Override
    public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) {
        Log.i(TAG, "animateChange: ");
        return false;
    }

    //RecyclerView动画的执行方式并不是立即执行，而是每帧执行一次，比如两帧之间添加了多个Item，
    // 则会将这些将要执行的动画Pending住，保存在成员变量中，等到下一帧一起执行。该方法执行的前提是前面animateXxx()返回true
    @Override
    public void runPendingAnimations() {
        Log.i(TAG, "runPendingAnimations: ");
        boolean hasRemove = !mPendingRemovals.isEmpty();
        boolean hasMove = !mPendingMoves.isEmpty();
        boolean hasChange = !mPendingChanges.isEmpty();
        boolean hasAdd = !mPendingAdditions.isEmpty();
        if (!hasRemove && !hasMove && !hasChange && !hasAdd) {
            Log.i(TAG, "runPendingAnimations: 没有要执行的动画");
            return;
        }
        //1执行remove动画
        if(hasRemove){
            final ArrayList<ViewHolder> removes=new ArrayList<>();
            removes.addAll(mPendingRemovals);
            mPendingRemovals.clear();
            for (ViewHolder holder : removes) {
                startRemoveAnimation(holder);
            }
        }


        //2执行move动画

        //3执行change动画

        //4执行add动画
        if(hasAdd){
            //建立成员变量存放指定的动画,防止执行动画过程中有新的动画添加进来
            final ArrayList<ViewHolder> adds=new ArrayList<>();
            adds.addAll(mPendingAdditions);
            //把当前一批动画添加到正在执行的一批add动画中
            mAdditionsList.add(adds);
            mPendingAdditions.clear();
            Runnable adder=new Runnable() {
                @Override
                public void run() {
                    //执行动画
                    for(ViewHolder viewHolder:adds){
                        startAddAnimation(viewHolder);
                    }
                    adds.clear();
                    mAdditionsList.remove(adds);

                }
            };
            adder.run();
        }


    }

    //当某个item的动画应立即结束时调用的方法
    //停止某个Item的动画
    @Override
    public void endAnimation(ViewHolder item) {
        Log.i(TAG, "endAnimation: ");
    }

    //当所有项动画都应立即结束时调用的方法,例如滚动式要结束所有动画
    // //停止所有动画
    @Override
    public void endAnimations() {
        Log.i(TAG, "endAnimations: ");
    }

    private void startAddAnimation(final ViewHolder holder){
        ViewPropertyAnimator animate = holder.itemView.animate();
        animate.translationX(0);
        animate.setDuration(1000);
        mAddAnimations.add(holder);
        animate.setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                dispatchAddStarting(holder);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                dispatchAddFinished(holder);
                mAddAnimations.remove(holder);
                dispatchFinishedWhenDone();

            }

            @Override
            public void onAnimationCancel(Animator animation) {
                holder.itemView.setTranslationX(0);
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animate.start();
    }

    private void startRemoveAnimation(final ViewHolder holder){
        ViewPropertyAnimator animate = holder.itemView.animate();
        RecyclerView.LayoutParams params= (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
        animate.translationX(-(holder.itemView.getWidth()+params.rightMargin));
        animate.setDuration(1000);
        mRemoveAnimations.add(holder);
        animate.setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                dispatchRemoveStarting(holder);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                dispatchRemoveFinished(holder);
                mRemoveAnimations.remove(holder);
                holder.itemView.setTranslationX(0);
                dispatchFinishedWhenDone();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                holder.itemView.setTranslationX(0);
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animate.start();
    }

    /**
     * Check the state of currently pending and running animations. If there are none
     * pending/running, call {@link #dispatchAnimationsFinished()} to notify any
     * listeners.
     */
    void dispatchFinishedWhenDone() {
        if (!isRunning()) {
            dispatchAnimationsFinished();
        }
    }

    //是否有动画要执行或正在执行
    @Override
    public boolean isRunning() {
        Log.i(TAG, "isRunning: ");
        return (!mPendingAdditions.isEmpty()
                || !mPendingChanges.isEmpty()
                || !mPendingMoves.isEmpty()
                || !mPendingRemovals.isEmpty()
                || !mMoveAnimations.isEmpty()
                || !mRemoveAnimations.isEmpty()
                || !mAddAnimations.isEmpty()
                || !mChangeAnimations.isEmpty()
                || !mMovesList.isEmpty()
                || !mAdditionsList.isEmpty()
                || !mChangesList.isEmpty());
    }

    private static class MoveInfo {
        public ViewHolder holder;
        public int fromX, fromY, toX, toY;

        MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            this.holder = holder;
            this.fromX = fromX;
            this.fromY = fromY;
            this.toX = toX;
            this.toY = toY;
        }
    }

    private static class ChangeInfo {
        public ViewHolder oldHolder, newHolder;
        public int fromX, fromY, toX, toY;
        private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) {
            this.oldHolder = oldHolder;
            this.newHolder = newHolder;
        }

        ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder,
                   int fromX, int fromY, int toX, int toY) {
            this(oldHolder, newHolder);
            this.fromX = fromX;
            this.fromY = fromY;
            this.toX = toX;
            this.toY = toY;
        }

        @Override
        public String toString() {
            return "ChangeInfo{"
                    + "oldHolder=" + oldHolder
                    + ", newHolder=" + newHolder
                    + ", fromX=" + fromX
                    + ", fromY=" + fromY
                    + ", toX=" + toX
                    + ", toY=" + toY
                    + '}';
        }
    }


}
